LDR指令、LDR伪指令、ADR伪指令区别 |
您所在的位置:网站首页 › area test › LDR指令、LDR伪指令、ADR伪指令区别 |
引例如下: 先看一段代码: AREA test,CODE,READONLY ENTRY ldr r0,__main adr r0,__main ldr r0,=__main nop __main nop END 反汇编一下后 编译环境:realview 4.12 编译的时候设置 ROM1 :start_addr 0x30000000 、size 0x200000 RAM1 :start_addr 0x30200000 、 size:0x4000000 下面是反汇编的结果: \\ code pc_current binary code after asmcc 6: ldr r0,__main 0x300000D8 E59F0008 LDR R0,[PC,#0x0008] 7: adr r0,__main 0x300000DC E28F0004 ADD R0,PC,#0x00000004 8: ldr r0,=__main 0x300000E0 E59F0004 LDR R0,[PC,#0x0004] 9: nop 10: 11: EXPORT __main 12: __main 0x300000E4 E1A00000 NOP 13: b __main 0x300000E8 EAFFFFFE B 0x300000E8 0x300000EC 300000E8 ANDCC R0,R0,R8,ROR #1 下面来分析一下这三条指令 1、ldr r0,__main ;这条指令实现将__main位置中的值装入r0中 经过汇编后,__main将被一个相对于PC的表达式取代 __main => [pc,#4] ;应为arm指令是以三级流水线的执行,pc=pc_current+0x08 所以最后地址(pc+4)中的值装入r0中 总结:ldr r0, __main是根据__main对PC(pc_current+8)的相对位置(+4)读取其所在地址的值,因此可以在和___main标号的相对位置不变的情况下移动。 2、adr r0,__main ;小范围的地址读取伪指令 这是一条伪指令,总是会被汇编程序汇编为一个指令。汇编程序尝试产生单个 ADD 或 SUB 指令来装载该地址。如果不能在一个指令中构造该地址,则生成一个错误,并且汇编失败。 在这里是取得标号__main 的地址到 r0,因为地址是相对程序的,因此ADR产生依赖于位置的代码。 本例中会变成:ADD R0,PC,#0x00000004 。因此该代码可以在和标号相对位置不变的情况下移动。假如:这段代码在 0x30000000 运行,那么 adr r0, __main得到 r0 = 0x3000000c;如果在地址 0 运行,就是 0x0000000c 了。 3、ldr r0,=__main ;大范围的地址读取 LDR伪指令用于加载32位的立即数或一个地址值到指定寄存器。在汇编编译源程序时,LDR伪指令被编译器替换成一条合适的指令。若加载的常数未超出MOV或MVN的范围,则使用MOV或MVN指令代替该LDR伪指令,否则汇编器将常量放入文字池,并使用一条程序相对偏移的LDR指令从文字池读出常量。这个指令取得标号 __main 的绝对地址,这个绝对地址是在 link 的时候确定的,看上去这只是一个指令,但是它要占用 2 个 32bit 的空间,一条是指令,另一条是 __main 的数据(因为在编译的时候不能确定 __main的值,而且也不能用 mov 指令来给 r0 赋一个 32bit 的常量,所以需要多出一个空间存放 __main 的真正数据,在这里就是 0x300000EC这个地址,取其中的值300000E8 )。 因此可以看出,这个是绝对的寻址,不管这段代码在什么地方运行,它的结果都是 r0 = 300000E8 。
完整的总结一下吧: 1、ADR伪指令--- 小范围的地址读取 ADR伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中。在汇编编译器编译源程序时,ADR伪指令被编译器替换成一条合适的指令。通常,编译器用一条ADD指令或SUB指令来实现该ADR伪指令的功能,若不能用一条指令实现,则产生错误,编译失败。 ADR伪指令格式 :ADR{cond} register, expr 地址表达式expr的取值范围: 当地址值是字节对齐时,其取指范围为: +255 ~ 255B; 当地址值是字对齐时,其取指范围为: -1020 ~ 1020B; 2、ADRL伪指令----中等范围的地址读取 ADRL伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中,比ADR伪指令可以读取更大范围的地址。 在汇编编译器编译源程序时,ADRL伪指令被编译器替换成两条合适的指令。若不能用两条指令实现,则产生错误,编译失败。 ADRL伪指令格式:ADRL{cond} register, expr 地址表达式expr的取值范围: 当地址值是字节对齐时,其取指范围为: -64K~64K; 当地址值是字对齐时,其取指范围为: -256K~256K; 3、LDR伪指令-----大范围的地址读取 LDR伪指令用于加载32位的立即数或一个地址值到指定寄存器。在汇编编译源程序时,LDR伪指令被编译器替换成一条合适的指令。 若加载的常数未超出MOV或MVN的范围,则使用MOV或MVN指令代替该LDR伪指令,否则汇编器将常量放入文字池,并使用一条程序相对偏移的LDR指令从文字池读出常量。
|
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |